package com.yuncool.sky.system.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.yuncool.sky.system.domain.Subject;
import com.yuncool.sky.system.mapper.SubjectMapper;
import com.yuncool.sky.system.pojo.bo.SubjectBO;
import com.yuncool.sky.system.pojo.form.SubjectForm;
import com.yuncool.sky.system.pojo.vo.SubjectVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Auther XIE
 * @Date 2019/11/22 22:17
 * @Description 课程服务类
 * @Version 1.0
 */
@Service
@Slf4j
public class SubjectService extends ServiceImpl<SubjectMapper, Subject> {

    @Autowired
    SubjectMapper subjectMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 课程列表
     * 从缓存中查
     *
     * @param query
     * @return
     */
    public List<SubjectBO> subjectList(String query) {
        Set<String> keys = redisTemplate.keys("subject_" + query + "_*");
        List<SubjectBO> list = keys.stream()
                .map(s -> (SubjectBO) redisTemplate.opsForValue().get(s))
                .collect(Collectors.toList());
        return list;
    }

    /**
     * 缓存课程
     *
     * @param subjectBO
     */
    private void cacheOneSubject(SubjectBO subjectBO) {
        String key = "subject_" + subjectBO.getCid() + "_" + subjectBO.getId();
        if (!redisTemplate.hasKey(key)) {
            redisTemplate.opsForValue().set(key, subjectBO);
        }
    }

    /**
     * 计算进度条
     *
     * @param sold
     * @param sum
     * @return
     */
    private Double getProgress(String sold, String sum) {
        return (Double.parseDouble(sum) - Double.parseDouble(sold)) / Double.parseDouble(sum) * 100;
    }

    /**
     * 异步缓存数据
     */
    @Async
    public void cacheData() {
        if (!redisTemplate.hasKey("CACHE_FLAG")) {
            System.out.println("缓存数据....");
            redisTemplate.opsForValue().set("CACHE_FLAG", "已缓存");
            List<SubjectBO> subjectList = subjectMapper.selectList(new QueryWrapper<>()).stream()
                    .map(subject ->
                            new SubjectBO(
                                    subject.getId(),
                                    subject.getCid().toString(),
                                    subject.getImgUrl(),
                                    subject.getTitle(),
                                    getContent(subject.getContent()),
                                    subject.getTeacher(),
                                    subject.getSold(),
                                    subject.getSum(),
                                    subject.getStartTime(),
                                    getProgress(subject.getSold(), subject.getSum()))
                    ).collect(Collectors.toList());
            subjectList.forEach(this::cacheOneSubject);
        }

    }

    /**
     * 工具类:切割长文本
     *
     * @param content
     * @return
     */
    public String getContent(String content) {
        if (content.length() > 50) {
            return content.substring(0, 50) + "...";
        }
        return content + "...";
    }

    /**
     * 判断用户是否已经抢过课了
     *
     * @param userNumber
     * @return
     */
    public Boolean checkRecord(String userNumber) {
        String key = "record_" + userNumber;
        return redisTemplate.hasKey(key);
    }

    /**
     * 抢课
     *
     * @param subjectForm
     * @return
     */
    public synchronized Map<String, Object> selectSubject(SubjectForm subjectForm) {
        Map<String, Object> map = new HashMap<>();
        String key = "subject_" + subjectForm.getQuery() + "_" + subjectForm.getSid();
        SubjectBO subjectBO = (SubjectBO) redisTemplate.opsForValue().get(key);
        if (subjectBO.getSum().equals(subjectBO.getSold())) {
            map.put("code", "02");
            map.put("message", "无剩余名额");
            log.info("用户:" + subjectForm.getUserNumber() + ",抢课失败!");
            return map;
        }
        //减少名额
        subjectBO.setSold(String.valueOf(Integer.valueOf(subjectBO.getSold()) + 1));
        subjectBO.setProgress(getProgress(subjectBO.getSold(), subjectBO.getSum()));
        redisTemplate.opsForValue().set(key, subjectBO);
        redisTemplate.opsForValue().set("record_" + subjectForm.getUserNumber(), subjectForm.getSid());
        //TODO 异步通知消息队列干活
        log.info("用户:" + subjectForm.getUserNumber() + "抢课成功!");
        rabbitTemplate.convertAndSend("select-queue", subjectBO);
        rabbitTemplate.convertAndSend("record-queue", subjectForm);
        map.put("code", "00");
        map.put("message", "抢课成功");
        return map;
    }

    /**
     * 后台:课程列表
     *
     * @param subjectForm
     * @return
     */
    public List<SubjectVo> sysSubjectList(SubjectForm subjectForm) {
        PageHelper.startPage(subjectForm.getPages(), subjectForm.getPageSize());
        return subjectMapper.subjectList();
    }

    /**
     * 后台:课程总数
     *
     * @return
     */
    public Integer sysSubjectSize() {
        return this.count();
    }
}
